package org.jeecg.modules.pos.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.lang.Snowflake;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.apache.commons.lang3.ObjectUtils;
import org.jeecg.common.exception.JeecgBootException;
import org.jeecg.common.util.TokenUtils;
import org.jeecg.modules.business.entity.*;
import org.jeecg.modules.business.enums.FeeSubjectType;
import org.jeecg.modules.business.enums.FeeType;
import org.jeecg.modules.business.service.*;
import org.jeecg.modules.kc.entity.KcDepositoryInGoods;
import org.jeecg.modules.kc.service.IKcDepositoryInGoodsService;
import org.jeecg.modules.pos.PosBookingStateEnum;
import org.jeecg.modules.pos.TableStateEnum;
import org.jeecg.modules.pos.entity.*;
import org.jeecg.modules.pos.mapper.PosOrderGoodsMapper;
import org.jeecg.modules.pos.service.*;
import org.jeecg.modules.pos.vo.PosBooingOrderGoods;
import org.jeecg.modules.rooms.entity.CesGoods;
import org.jeecg.modules.rooms.service.CesGoodsServiceImpl;
import org.springframework.stereotype.Service;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @Description: pos_order_goods
 * @Author: jeecg-boot
 * @Date: 2023-04-13
 * @Version: V1.0
 */
@Service
public class PosOrderGoodsServiceImpl extends ServiceImpl<PosOrderGoodsMapper, PosOrderGoods> implements IPosOrderGoodsService {

    @Resource
    private IPosOrderGoodsDetailService posOrderGoodsDetailService;
    @Resource
    private IPosTableService posTableService;
    @Resource
    private IBusRoomsLivingOrderService livingOrderService;
    @Resource
    private IBusBookingRoomsService bookingRoomsService;
    @Resource
    private IBusOrderFeeService orderFeeService;
    @Resource
    private IBusOrderFeeGoodsService orderFeeGoodsService;

    @Resource
    private CesGoodsServiceImpl cesGoodsService;

    @Resource
    private IPosBookingService posBookingService;

    @Resource
    private IKcDepositoryInGoodsService depositoryInGoodsService;

    @Resource
    private IPosOrderTeamService posOrderTeamService;

    /**
     * 通过桌台id查询订单
     */
    @Override
    public PosOrderGoods getOrderByTableId(String tableId) {
        LambdaQueryWrapper<PosOrderGoods> queryWrapper = new LambdaQueryWrapper<PosOrderGoods>().eq(PosOrderGoods::getStatus, 0)
                .eq(PosOrderGoods::getPosTableId, tableId).orderByDesc(PosOrderGoods::getCreateTime).last("limit 1");
        PosOrderGoods orderGood = getOne(queryWrapper);
        if (orderGood == null) {
            throw new JeecgBootException("未找到订单");
        }
        List<PosOrderGoodsDetail> goodsDetailList = posOrderGoodsDetailService.getGoodsDetail(orderGood.getCode());
        orderGood.setPosOrderGoodsDetailList(goodsDetailList);
        return orderGood;
    }

    @Override
    public PosOrderGoods getOrderTeamByTableId(String tableId) {
        LambdaQueryWrapper<PosOrderGoods> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(PosOrderGoods::getPosTableId, tableId);
        lambdaQueryWrapper.eq(PosOrderGoods::getStatus, 0);
        // 还未开台的预约单不显示
        lambdaQueryWrapper.eq(PosOrderGoods::getIsBooking, false);
        lambdaQueryWrapper.orderByDesc(PosOrderGoods::getCreateTime);
        lambdaQueryWrapper.last("limit 1");
        PosOrderGoods posOrderGood = getOne(lambdaQueryWrapper);
        if (posOrderGood == null || StrUtil.isEmpty(posOrderGood.getTeamId())) {
            return posOrderGood;
        }
        PosOrderTeam team = posOrderTeamService.getById(posOrderGood.getTeamId());
        if (team != null && !team.getIsDelete()) {
            posOrderGood.setTeamIndex(team.getSortIndex());
            posOrderGood.setIsMain(posOrderGood.getId().equals(team.getOrderId()));
        }
        return posOrderGood;
    }

    /**
     * 挂房账
     */
    @Override
    public Boolean addRoomFee(PosOrderGoods posOrderGoods, String hotelId) {
        if (posOrderGoods.getToRoomFeeOrderId().isEmpty()) {
            throw new JeecgBootException("未找到挂房费的订单");
        }
        BusRoomsLivingOrder livingOrder = livingOrderService.getById(posOrderGoods.getToRoomFeeOrderId());
        if (ObjectUtil.isEmpty(livingOrder)) {
            throw new JeecgBootException("未找到房间的入住单订单");
        }
        BusBookingRooms bookingRoom = bookingRoomsService.getById(livingOrder.getBookingRoomId());
        if (ObjectUtil.isEmpty(bookingRoom)) {
            throw new JeecgBootException("未找到订单关联的房间");
        }
        if (StrUtil.isEmpty(posOrderGoods.getId()) && CollUtil.isEmpty(posOrderGoods.getPosOrderGoodsDetailList())) {
            throw new JeecgBootException("未找到商品订单");
        }
        PosOrderGoods orderGoods;
        if (CollUtil.isNotEmpty(posOrderGoods.getPosOrderGoodsDetailList())) {
            // 如果存在未加入订单的商品,先加入订单
            orderGoods = addOrder(posOrderGoods);
        } else {
            orderGoods = getById(posOrderGoods.getId());
            orderGoods.setToRoomFeeOrderId(posOrderGoods.getToRoomFeeOrderId());
        }
        if (StrUtil.isNotEmpty(orderGoods.getPosTableId())) {
            PosTable posTable = posTableService.getById(orderGoods.getPosTableId());
            if (ObjectUtil.isEmpty(posTable)) {
                throw new JeecgBootException("未找到桌号");
            }
            posTable.setState(4);
            posTableService.updateById(posTable);
        }
        List<PosOrderGoodsDetail> goodsDetailList = posOrderGoodsDetailService.list(Wrappers.<PosOrderGoodsDetail>lambdaQuery()
                .eq(PosOrderGoodsDetail::getOrderId, orderGoods.getCode()));
        List<BusOrderFee> orderFeeList = new ArrayList<>();
        List<BusOrderFeeGoods> feeGoodsList = new ArrayList<>();
        goodsDetailList.forEach(e -> {
            long id = new Snowflake().nextId();
            BusOrderFee busOrderFee = new BusOrderFee();
            busOrderFee.setId(StrUtil.toString(id));
            busOrderFee.setFeeType(FeeType.CONSUME.getKey());
            busOrderFee.setSubjectType(FeeSubjectType.DIAN_PIN.getKey());
            busOrderFee.setMoney(e.getPayMoney().multiply(BigDecimal.valueOf(e.getNum())));
            busOrderFee.setOriginalMoney(e.getPayMoney().multiply(BigDecimal.valueOf(e.getNum())));
            busOrderFee.setDayTime(new Date());
            busOrderFee.setHotelId(hotelId);
            busOrderFee.setRoomId(bookingRoom.getRoomId());
            busOrderFee.setLivingOrderId(orderGoods.getToRoomFeeOrderId());
            BusOrderFeeGoods orderFeeGoods = new BusOrderFeeGoods();
            orderFeeGoods.setHotelId(hotelId);
            orderFeeGoods.setNum(e.getNum());
            orderFeeGoods.setGoodsId(e.getGoodsId());
            orderFeeGoods.setLivingOrderId(orderGoods.getToRoomFeeOrderId());
            orderFeeGoods.setPrice(e.getMoney());
            orderFeeGoods.setOrderFeeId(busOrderFee.getId());
            orderFeeList.add(busOrderFee);
            feeGoodsList.add(orderFeeGoods);
        });
        orderFeeService.saveBatch(orderFeeList);
        orderFeeGoodsService.saveBatch(feeGoodsList);
        orderGoods.setStatus(1);
        updateById(orderGoods);
        return true;
    }

    @Override
    public PosOrderGoods addOrder(PosOrderGoods posOrderGoods) {
        // 直接点击结账时id为空
        if (StrUtil.isEmpty(posOrderGoods.getId())) {
            // 创建取餐号
            setOrderTableNo(posOrderGoods);
            posOrderGoods.setCode(randomNumber("P"));
        } else {
            // 存在订单(桌台点单,取单支付)
            List<PosOrderGoodsDetail> list = posOrderGoods.getPosOrderGoodsDetailList();
            String toRoomFeeOrderId = posOrderGoods.getToRoomFeeOrderId();
            String tableId = posOrderGoods.getPosTableId();
            String tableNo = posOrderGoods.getTableNo();
            Boolean isPending = posOrderGoods.getIsPending();
            // 找出订单,将订单重新赋值
            posOrderGoods = getById(posOrderGoods.getId());
            posOrderGoods.setPosOrderGoodsDetailList(list);
            posOrderGoods.setToRoomFeeOrderId(toRoomFeeOrderId);
            posOrderGoods.setPosTableId(tableId);
            posOrderGoods.setTableNo(tableNo);
            posOrderGoods.setIsPending(isPending);
        }
        // 完善订单和订单详情数据
        repairOrderGoods(posOrderGoods);
        // 添加商品消费详情
        posOrderGoodsDetailService.saveBatch(posOrderGoods.getPosOrderGoodsDetailList());
        //桌台下单或者挂单时商品减库存
        for (PosOrderGoodsDetail posOrderGoodsDetail : posOrderGoods.getPosOrderGoodsDetailList()) {
            // 下单商品时
            addSellGoods(posOrderGoodsDetail, null);
            // 下单的是套餐时
            if (StrUtil.isNotEmpty(posOrderGoodsDetail.getThaliId())) {
                // 添加套餐 出库对象
                KcDepositoryInGoods depositoryInGoods = addDepositoryInGood(posOrderGoodsDetail);
                depositoryInGoods.setNum(-depositoryInGoods.getNum());
                depositoryInGoodsService.save(depositoryInGoods);
                // 循环添加套餐下的商品 出库对象
                posOrderGoodsDetail.getChildDetails().forEach(e -> {
                    e.setId(String.valueOf(IdWorker.getId()));
                    e.setParentId(posOrderGoodsDetail.getId());
                    addSellGoods(e, depositoryInGoods.getId());
                });
                // 添加套餐下商品消费详情
                posOrderGoodsDetailService.saveBatch(posOrderGoodsDetail.getChildDetails());
            }
        }
        // 修改桌台状态
        LambdaUpdateWrapper<PosTable> lambdaUpdateWrapper = new LambdaUpdateWrapper<>();
        lambdaUpdateWrapper.eq(PosTable::getId, posOrderGoods.getPosTableId());
        lambdaUpdateWrapper.set(PosTable::getState, 2);
        posTableService.update(lambdaUpdateWrapper);
        saveOrUpdate(posOrderGoods);
        return posOrderGoods;
    }


    /**
     * 添加预约单
     */
    @Override
    public Boolean addBookingOrder(PosBookingOrder bookingOrder) {
        if (bookingOrder.getArriveTime() == null) {
            throw new JeecgBootException("请选择预约时间");
        }
        if (CollUtil.isEmpty(bookingOrder.getTableIds())) {
            throw new JeecgBootException("请选择桌台");
        }
        List<PosTable> tableList = posTableService.list(Wrappers.<PosTable>lambdaQuery().in(PosTable::getId, bookingOrder.getTableIds()));
        if (tableList.size() != bookingOrder.getTableIds().size()) {
            throw new JeecgBootException("未找到桌台");
        }
        if (StrUtil.isEmpty(bookingOrder.getId())) {
            bookingOrder.setCode(randomNumber("Y"));
        }
        List<PosOrderGoods> orderGoodsList = new ArrayList<>();
        List<PosOrderGoodsDetail> targetOrderGoodsDetailList = new ArrayList<>();
        tableList.forEach(e -> {
            PosOrderGoods posOrderGoods = new PosOrderGoods();
            posOrderGoods.setIsBooking(true);
            posOrderGoods.setBookingCode(bookingOrder.getCode());
            posOrderGoods.setCode(randomNumber("P"));
            posOrderGoods.setPosTableId(e.getId());
            posOrderGoods.setPosType(e.getPosTypeId());
            posOrderGoods.setHotelId(bookingOrder.getHotelId());
            posOrderGoods.setTenantId(TokenUtils.currentTenantId());
            BigDecimal amount = new BigDecimal(0);
            if (bookingOrder.getPosOrderGoodsDetailList() != null) {
                for (PosOrderGoodsDetail posOrderGoodsDetail : bookingOrder.getPosOrderGoodsDetailList()) {
                    PosOrderGoodsDetail targetorderGoodsDetail = new PosOrderGoodsDetail();
                    targetorderGoodsDetail.setGoodsId(posOrderGoodsDetail.getGoodsId());
                    targetorderGoodsDetail.setNum(posOrderGoodsDetail.getNum());
                    targetorderGoodsDetail.setMoney(posOrderGoodsDetail.getMoney());
                    targetorderGoodsDetail.setCouponMoney(posOrderGoodsDetail.getMoney());
                    targetorderGoodsDetail.setPayMoney(posOrderGoodsDetail.getMoney());
                    targetorderGoodsDetail.setOrderId(posOrderGoods.getCode());
                    targetorderGoodsDetail.setTenantId(TokenUtils.currentTenantId());
                    targetorderGoodsDetail.setHotelId(bookingOrder.getHotelId());
                    amount = amount.add(posOrderGoodsDetail.getMoney().multiply(BigDecimal.valueOf(posOrderGoodsDetail.getNum())));
                    targetOrderGoodsDetailList.add(targetorderGoodsDetail);
                }
            }
            posOrderGoods.setMoney(amount);
            orderGoodsList.add(posOrderGoods);
        });
        posOrderGoodsDetailService.saveBatch(targetOrderGoodsDetailList);
        saveBatch(orderGoodsList);
        return posBookingService.saveOrUpdate(bookingOrder);
    }

    /***/
    @Override
    public PosBookingOrder getBookingOrderById(String bookingId) {
        PosBookingOrder bookingOrder = posBookingService.getById(bookingId);
        if (bookingOrder == null) {
            throw new JeecgBootException("未找到预约单");
        }
        List<PosOrderGoods> orderGoodsList = list(Wrappers.<PosOrderGoods>lambdaQuery().eq(PosOrderGoods::getBookingCode, bookingOrder.getCode()));
        if (orderGoodsList.isEmpty()) {
            throw new JeecgBootException("未找到相关订单");
        }
        List<PosOrderGoodsDetail> goodsDetail = posOrderGoodsDetailService.getGoodsDetail(orderGoodsList.get(0).getCode());
        bookingOrder.setPosOrderGoodsDetailList(goodsDetail);
        List<String> tableIds = orderGoodsList.stream().map(PosOrderGoods::getPosTableId).collect(Collectors.toList());
        if (tableIds.isEmpty()) {
            throw new JeecgBootException("未找到相关桌台");
        }
        List<PosTable> tableList = posTableService.listByIds(tableIds);
        bookingOrder.setTableList(tableList);
        return bookingOrder;
    }

    /**
     * 编辑预定单
     */
    @Override
    public Boolean editBookingOrder(PosBookingOrder bookingOrder) {
        List<PosOrderGoods> orderGoodsList = list(Wrappers.<PosOrderGoods>lambdaQuery()
                .eq(PosOrderGoods::getBookingCode, bookingOrder.getCode()));
        List<String> orderGoodsCodes = orderGoodsList.stream().map(PosOrderGoods::getCode).collect(Collectors.toList());
        List<PosOrderGoodsDetail> goodsDetailList = new ArrayList<>();
        if (!orderGoodsCodes.isEmpty()) {
            goodsDetailList = posOrderGoodsDetailService.list(Wrappers.<PosOrderGoodsDetail>lambdaQuery()
                    .in(PosOrderGoodsDetail::getOrderId, orderGoodsCodes));
        }
        // 相当于重新添加一次预约单
        Boolean res = addBookingOrder(bookingOrder);
        // 删除预约单的关联订单和订单详情
        if (res) {
            removeBatchByIds(orderGoodsList);
            posOrderGoodsDetailService.removeBatchByIds(goodsDetailList);
        }
        return true;
    }


    /**
     * 根据桌号查询今日预约单
     */
    @Override
    public List<PosBookingOrder> getBookingByTableId(String tableId) {
        // 找到预约单
        List<PosBookingOrder> bookingOrders = posBookingService.getTodayBooking();
        if (bookingOrders.isEmpty()) {
            return bookingOrders;
        }
        List<String> codes = bookingOrders.stream().map(PosBookingOrder::getCode).collect(Collectors.toList());
        if (codes.isEmpty()) {
            return new ArrayList<>();
        }
        // 找到预约单下订单
        List<PosOrderGoods> orderGoodsList = list(Wrappers.<PosOrderGoods>lambdaQuery().in(PosOrderGoods::getBookingCode, codes));
        List<String> findCodes = orderGoodsList.stream().filter(e -> tableId.equals(e.getPosTableId())).map(PosOrderGoods::getBookingCode).collect(Collectors.toList());
        if (findCodes.isEmpty()) {
            return new ArrayList<>();
        }
        return bookingOrders.stream().filter(e -> findCodes.contains(e.getCode())).collect(Collectors.toList());
    }

    /**
     * 预定开台
     */
    @Override
    public Boolean addOrderByBookingId(String bookingId) {
        PosBookingOrder bookingOrder = posBookingService.getById(bookingId);
        if (bookingOrder == null) {
            throw new JeecgBootException("未找到预约单");
        }
        if (!PosBookingStateEnum.NO_ARRIVE.getKey().equals(bookingOrder.getState())) {
            throw new JeecgBootException(Objects.requireNonNull(PosBookingStateEnum.val(bookingOrder.getState())).getTitle() + "的预定单不能开台");
        }
        // 找出预约单下所有订单
        List<PosOrderGoods> orderGoodsList = list(Wrappers.<PosOrderGoods>lambdaQuery()
                .eq(PosOrderGoods::getBookingCode, bookingOrder.getCode()).eq(PosOrderGoods::getStatus, 0));
        List<String> tableId = orderGoodsList.stream().map(PosOrderGoods::getPosTableId).collect(Collectors.toList());
        if (orderGoodsList.isEmpty() || tableId.isEmpty()) {
            throw new JeecgBootException("未找到预约的订单");
        }
        List<PosTable> tableList = posTableService.listByIds(tableId);
        if (tableList.size() != tableId.size()) {
            throw new JeecgBootException("未找到预约的桌台");
        }
        // 预约单中有桌台已经被使用，无法开台
        List<PosTable> useTables = tableList.stream().filter(e -> !TableStateEnum.EMPTY.getKey().equals(e.getState())).collect(Collectors.toList());
        if (!useTables.isEmpty()) {
            throw new JeecgBootException("桌台号" + useTables.get(0).getName() + "正在被使用，无法开台");
        }
        // 扣减库存，添加销售出库记录
        List<String> orderGoodsCodes = orderGoodsList.stream().map(PosOrderGoods::getCode).collect(Collectors.toList());
        if (orderGoodsCodes.isEmpty()) {
            throw new JeecgBootException("未找到预约的单");
        }
        List<PosOrderGoodsDetail> targetOrderGoodsDetailList = posOrderGoodsDetailService.list(Wrappers.<PosOrderGoodsDetail>lambdaQuery()
                .in(PosOrderGoodsDetail::getOrderId, orderGoodsCodes));
        for (PosOrderGoodsDetail posOrderGoodsDetail : targetOrderGoodsDetailList) {
            CesGoods cesGoods = cesGoodsService.getById(posOrderGoodsDetail.getGoodsId());
            if (ObjectUtils.isNotEmpty(cesGoods)) {
                Integer c = cesGoods.getInventory() - posOrderGoodsDetail.getNum();
                if (c < 0) {
                    throw new JeecgBootException(cesGoods.getName() + "库存不足");
                }
                cesGoods.setInventory(c);
                cesGoodsService.updateById(cesGoods);
                KcDepositoryInGoods depositoryInGoods = addDepositoryInGood(posOrderGoodsDetail);
                depositoryInGoodsService.addSell(depositoryInGoods);
            }
        }
        // 如果订单下有商品就将房间状态改为待下单，没有商品就改为待结账
        if (targetOrderGoodsDetailList.isEmpty()) {
            tableList.forEach(e -> e.setState(TableStateEnum.WILL_ORDER.getKey()));
        } else {
            tableList.forEach(e -> e.setState(TableStateEnum.WILL_PAYMENT.getKey()));
        }
        posTableService.updateBatchById(tableList);
        orderGoodsList.forEach(e -> e.setIsBooking(false));
        updateBatchById(orderGoodsList);
        bookingOrder.setState(PosBookingStateEnum.ARRIVE.getKey());
        return posBookingService.updateById(bookingOrder);
    }

    /**
     * 预订单退订
     */
    @Override
    public Boolean cancelBooking(PosBookingOrder bookingOrder) {
        PosBookingOrder findBookingOrder = posBookingService.getById(bookingOrder.getId());
        if (findBookingOrder == null) {
            throw new JeecgBootException("未找到预约单");
        }
        findBookingOrder.setState(PosBookingStateEnum.RETRUN_MONEY.getKey());
        findBookingOrder.setRemark(bookingOrder.getRemark());
        List<PosOrderGoods> orderGoodsList = list(Wrappers.<PosOrderGoods>lambdaQuery().eq(PosOrderGoods::getBookingCode, findBookingOrder.getCode()));
//        List<String> codes = orderGoodsList.stream().map(PosOrderGoods::getCode).collect(Collectors.toList());
//        if (!codes.isEmpty()){
//
//        }
//        List<PosOrderGoodsDetail> goodsDetailList = posOrderGoodsDetailService.list(Wrappers.<PosOrderGoodsDetail>lambdaQuery().in(PosOrderGoodsDetail::getOrderId, codes));
//        goodsDetailList.forEach(e -> {
//            KcDepositoryInGoods depositoryInGoods = addDepositoryInGood(e);
//            cesGoodsService.saleReturn(depositoryInGoods);
//        });
        return posBookingService.updateById(findBookingOrder);
    }

    /**
     * 联台
     */
    @Override
    public Boolean mergePosOrder(String hotelId, String mainPosOrderId, List<String> posOrderIds) {
        PosOrderGoods mainOrderGoods = getById(mainPosOrderId);
        if (mainOrderGoods == null || mainOrderGoods.getStatus() == 1) {
            throw new JeecgBootException("未找到订单");
        }
        if (CollUtil.isEmpty(posOrderIds)) {
            throw new JeecgBootException("请选择需要联台的订单");
        }
        List<PosOrderGoods> orderGoods = listByIds(posOrderIds);
        if (orderGoods.size() != posOrderIds.size()) {
            throw new JeecgBootException("未找到需要联台的订单");
        }
        if (StrUtil.isEmpty(mainOrderGoods.getTeamId())) {
            PosOrderTeam team = posOrderTeamService.addBusTeams(mainOrderGoods.getHotelId(), mainOrderGoods.getId());
            mainOrderGoods.setTeamId(team.getId());
        }
        // 找出被联台订单的已经联房的组号
        Set<String> teamIds = orderGoods.stream().map(PosOrderGoods::getTeamId).filter(e -> StrUtil.isNotEmpty(e)
                && !e.equals(mainOrderGoods.getTeamId())).collect(Collectors.toSet());
        // 删除联房组
        if (!teamIds.isEmpty()) {
            posOrderTeamService.update(Wrappers.<PosOrderTeam>lambdaUpdate().in(PosOrderTeam::getId, teamIds).set(PosOrderTeam::getIsDelete, true));
            // 找出所有订单，包含被联房关联的
            List<PosOrderGoods> nextOrder = list(Wrappers.<PosOrderGoods>lambdaQuery().in(PosOrderGoods::getTeamId, teamIds));
            orderGoods.addAll(nextOrder);
        }
        orderGoods.forEach(e -> e.setTeamId(mainOrderGoods.getTeamId()));
        orderGoods.add(mainOrderGoods);
        return updateBatchById(orderGoods);
    }

    /**
     * 取消联台
     */
    @Override
    public Boolean returnMergePosOrder(String posOrderId) {
        PosOrderGoods posOrder = getById(posOrderId);
        if (posOrder == null) {
            throw new JeecgBootException("未找到需要取消联台的订单");
        }
        PosOrderTeam team = posOrderTeamService.getById(posOrder.getTeamId());
        if (team == null || team.getIsDelete()) {
            throw new JeecgBootException("未找到关联号");
        }
        List<PosOrderGoods> orderGoodsList = list(Wrappers.<PosOrderGoods>lambdaQuery().eq(PosOrderGoods::getTeamId, team.getId()));
        if (orderGoodsList.size() <= 2) {
            orderGoodsList.forEach(e -> e.setTeamId(""));
            team.setIsDelete(true);
            posOrderTeamService.updateById(team);
            return updateBatchById(orderGoodsList);
        }
        posOrder.setTeamId("");
        return updateById(posOrder);
    }

    /**
     * 换桌
     */
    @Override
    public Boolean changeTable(String posOrderId, String tableId) {
        PosOrderGoods orderGoods = getById(posOrderId);
        if (orderGoods == null) {
            throw new JeecgBootException("未找到订单");
        }
        PosTable posTable = posTableService.getById(tableId);
        if (posTable == null) {
            throw new JeecgBootException("未找到要换的桌台");
        }
        if (!TableStateEnum.EMPTY.getKey().equals(posTable.getState())) {
            throw new JeecgBootException("要换的桌台不是空桌");
        }
        PosTable originalTable = posTableService.getById(orderGoods.getPosTableId());
        if (originalTable == null) {
            throw new JeecgBootException("未找到要换原桌台");
        }
        orderGoods.setPosTableId(posTable.getId());
        posTable.setState(originalTable.getState());
        posTable.setState(TableStateEnum.WILL_CLEAN.getKey());
        ArrayList<PosTable> posTableList = new ArrayList<>();
        posTableList.add(posTable);
        posTableList.add(originalTable);
        posTableService.updateBatchById(posTableList);
        return updateById(orderGoods);
    }

    /**
     * 转菜
     */
    @Override
    public Boolean transferDishes(String posOrderId, List<String> orderGoodsDetailIds) {
        if (CollUtil.isEmpty(orderGoodsDetailIds)) {
            return true;
        }
        PosOrderGoods orderGoods = getById(posOrderId);
        if (orderGoods == null) {
            throw new JeecgBootException("未找到目标桌台订单");
        }
        List<PosOrderGoodsDetail> orderGoodsDetailList = posOrderGoodsDetailService.listByIds(orderGoodsDetailIds);
        if (orderGoodsDetailList.size() != orderGoodsDetailIds.size()) {
            throw new JeecgBootException("未找到需要转菜的商品");
        }
        // 被转菜的订单
        PosOrderGoods originalOrderGoods = getOne(Wrappers.<PosOrderGoods>lambdaQuery()
                .eq(PosOrderGoods::getCode, orderGoodsDetailList.get(0).getOrderId()));
        if (originalOrderGoods == null) {
            throw new JeecgBootException("未找到被转菜的订单");
        }
        // 被转的菜品总价
        BigDecimal transferMoney = new BigDecimal(0);
        orderGoodsDetailList.forEach(e -> {
            e.setOrderId(orderGoods.getCode());
            transferMoney.add(e.getMoney().multiply(BigDecimal.valueOf(e.getNum())));
        });
        orderGoods.setMoney(orderGoods.getMoney().divide(transferMoney));
        originalOrderGoods.setMoney(originalOrderGoods.getMoney().add(transferMoney));
        ArrayList<PosOrderGoods> orderGoodsList = new ArrayList<>(2);
        orderGoodsList.add(orderGoods);
        orderGoodsList.add(originalOrderGoods);
        updateBatchById(orderGoodsList);
        // TODO: 2023/11/7 当桌台菜全部转走时，是否要改变桌台状态
        return posOrderGoodsDetailService.updateBatchById(orderGoodsDetailList);
    }

    @Override
    public Page<PosBooingOrderGoods> getBookingOrderPage(PosBookingOrder bookingOrder, Page<PosBooingOrderGoods> page, DateTime startTime, DateTime endTime) {
        return page.setRecords(baseMapper.getBookingOrderPage(bookingOrder, page, startTime, endTime));
    }


    /**
     * 设置订单的桌号/取餐号
     */
    private void setOrderTableNo(PosOrderGoods posOrderGoods) {
        if (StrUtil.isEmpty(posOrderGoods.getPosTableId())) {
            // 找出今日最后的一个账单
            LocalDateTime localDateTime = LocalDateTime.now().withNano(0).withSecond(0).withMinute(0).withHour(0);
            LocalDateTime[] arr = new LocalDateTime[]{localDateTime, localDateTime.withHour(23).withMinute(59)};
            LambdaQueryWrapper<PosOrderGoods> lambdaQueryWrapper = new LambdaQueryWrapper<>();
            lambdaQueryWrapper.eq(PosOrderGoods::getHotelId, posOrderGoods.getHotelId());
            lambdaQueryWrapper.ge(PosOrderGoods::getCreateTime, arr[0]);
            lambdaQueryWrapper.le(PosOrderGoods::getCreateTime, arr[1]);
            lambdaQueryWrapper.and(o -> o.isNull(PosOrderGoods::getPosTableId).or().eq(PosOrderGoods::getPosTableId, ""));
            Page<PosOrderGoods> page = new Page<>(1, 1);
            lambdaQueryWrapper.orderByDesc(PosOrderGoods::getCreateTime);
            IPage<PosOrderGoods> pageList = page(page, lambdaQueryWrapper);
            // 设置取餐号
            if (ObjectUtils.isNotEmpty(pageList.getRecords())) {
                String no = pageList.getRecords().get(0).getTableNo();
                try {
                    Integer newNo = Integer.parseInt(no) + 1;
                    posOrderGoods.setTableNo(String.format("%03d", newNo));
                } catch (NumberFormatException ex) {
                    posOrderGoods.setTableNo("001");
                }
            } else {
                posOrderGoods.setTableNo("001");
            }
        }

    }

    /**
     * 增加订单详情，创建出库记录，扣减库存
     */
    private void addSellGoods(PosOrderGoodsDetail posOrderGoodsDetail, String parentId) {
        if (StrUtil.isNotEmpty(posOrderGoodsDetail.getGoodsId())) {
            CesGoods cesGoods = cesGoodsService.getById(posOrderGoodsDetail.getGoodsId());
            if (ObjectUtils.isNotEmpty(cesGoods)) {
                Integer c = cesGoods.getInventory() - posOrderGoodsDetail.getNum();
                if (c < 0) {
                    throw new JeecgBootException(cesGoods.getName() + "库存不足");
                }
                cesGoods.setInventory(c);
                cesGoodsService.updateById(cesGoods);
                KcDepositoryInGoods depositoryInGoods = addDepositoryInGood(posOrderGoodsDetail);
                depositoryInGoods.setParentId(parentId);
                depositoryInGoodsService.addSell(depositoryInGoods);
            }
        }

    }

    /**
     * 完善订单数据
     */
    private void repairOrderGoods(PosOrderGoods posOrderGoods) {
        posOrderGoods.setTenantId(TokenUtils.currentTenantId());
        BigDecimal amount = BigDecimal.ZERO;
        if (ObjectUtil.isNotEmpty(posOrderGoods.getMoney())) {
            amount = posOrderGoods.getMoney();
        }
        for (PosOrderGoodsDetail posOrderGoodsDetail : posOrderGoods.getPosOrderGoodsDetailList()) {
            amount = amount.add(posOrderGoodsDetail.getMoney().multiply(BigDecimal.valueOf(posOrderGoodsDetail.getNum())));
            repairOrderGoodsDetail(posOrderGoodsDetail, posOrderGoods);
            // 订单详情为套餐时
            if (CollUtil.isNotEmpty(posOrderGoodsDetail.getChildDetails())) {
                posOrderGoodsDetail.getChildDetails().forEach(e -> repairOrderGoodsDetail(e, posOrderGoods));
                repairOrderGoodsDetail(posOrderGoodsDetail, posOrderGoods);
            }
        }
        posOrderGoods.setMoney(amount);
        posOrderGoods.setConsumeMoney(amount);
        posOrderGoods.setCreateTime(new Date());
        if (StrUtil.isNotEmpty(posOrderGoods.getToRoomFeeOrderId())) {
            posOrderGoods.setStatus(1);
            posOrderGoods.setSettleTime(new Date());
            posOrderGoods.setPayInfo("挂房账");
        }
    }

    /**
     * 完善订单详情数据
     */
    private void repairOrderGoodsDetail(PosOrderGoodsDetail posOrderGoodsDetail, PosOrderGoods posOrderGoods) {
        posOrderGoodsDetail.setTenantId(posOrderGoods.getTenantId());
        posOrderGoodsDetail.setHotelId(posOrderGoods.getHotelId());
        posOrderGoodsDetail.setCouponMoney(posOrderGoodsDetail.getMoney());
        posOrderGoodsDetail.setPayMoney(posOrderGoodsDetail.getMoney());
        posOrderGoodsDetail.setOrderId(posOrderGoods.getCode());
    }


    public KcDepositoryInGoods addDepositoryInGood(PosOrderGoodsDetail orderGoodsDetail) {
        KcDepositoryInGoods depositoryInGoods = new KcDepositoryInGoods();
        depositoryInGoods.setGoodsId(orderGoodsDetail.getGoodsId());
        depositoryInGoods.setThaliId(orderGoodsDetail.getThaliId());
        depositoryInGoods.setNum(orderGoodsDetail.getNum());
        depositoryInGoods.setFeeGoodId(orderGoodsDetail.getId());
        depositoryInGoods.setHotelId(orderGoodsDetail.getHotelId());
        depositoryInGoods.setCreateTime(new Date());
        return depositoryInGoods;
    }


    /**
     * 生成16位数字+prefix
     *
     * @param prefix
     * @return
     */
    private String randomNumber(String prefix) {
        int first = new Random(10).nextInt(8) + 1;
        int hashCode = UUID.randomUUID().toString().hashCode();
        if (hashCode < 0) {
            hashCode = -hashCode;
        }
        return prefix + first + String.format("%015d", hashCode);
    }
}
